package org.tangerinejunction.imstats.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import java.util.Calendar;

import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import org.tangerinejunction.imstats.data.IMDataset;
import org.tangerinejunction.imstats.data.TableFactory;
import org.tangerinejunction.imstats.logs.AdiumLogReader;
import org.tangerinejunction.imstats.util.Constants;
import org.tangerinejunction.imstats.util.Increment;
import org.tangerinejunction.imstats.util.TimeRange;

import prefuse.data.Table;

import com.michaelbaranov.microba.calendar.DatePicker;

/**
 * This is part of the new UI.  The ControlPanel contains all the
 * controls that that allow the user to create and manipulate
 * windows for analysis.
 * 
 * @author meganthorsen
 */
public class ControlPanel extends JPanel implements ActionListener
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 6330688249241891203L;
	
	public static final String ACCOUNT_VIEW = "Account view";
	public static final String ENTITY_VIEW = "Entity view";
	
	Application application;
	IMDataset dataset;
	Table dataTable;
	String viewType;
	TimeRange dateRange;
	
	JButton refresh;
	DatePicker startDatePicker;
	DatePicker endDatePicker;
	JRadioButton entityButton;
	JRadioButton accountButton;
	JComboBox presets;

	/**
	 * 
	 * @param application	the Application to which this ControlPanel belongs
	 * @param dataset		the dataset we want to manipulate
	 * @param viewType		whether we are viewing by Account or by Entity
	 * @param dateRange		the date range we want to analyze
	 * @param increment		the increment by which we want to analyze
	 */
	public ControlPanel(Application application, IMDataset dataset, String viewType, TimeRange dateRange, Increment increment)
	{
		setLayout(new BorderLayout());
		this.application = application;
		this.dataset = dataset;
		this.dateRange = dateRange;
		setDataTable(viewType, true);
		
		createComponents();
		layoutComponents();
		setupEvents();
		setPreferredSize(new Dimension(300, 175));
	}
	
	/**
	 * 
	 * @return	the start date selected for analysis
	 */
	public Calendar getStartCalendar()
	{
		Calendar value = Calendar.getInstance();
		value.setTime(startDatePicker.getDate());
		return value;
	}
	
	/**
	 * 
	 * @return	the end date selected for analysis
	 */
	public Calendar getEndCalendar()
	{
		Calendar value = Calendar.getInstance();
		value.setTime(endDatePicker.getDate());
		return value;
	}
	
	private void createComponents()
	{
		entityButton = new JRadioButton("Entity view");
		accountButton = new JRadioButton("Account view");
		if (viewType.equals(ACCOUNT_VIEW))
			accountButton.setSelected(true);
		else
			entityButton.setSelected(true);
		ButtonGroup group = new ButtonGroup();
		group.add(entityButton);
		group.add(accountButton);
		
		Calendar endOfMonth = Calendar.getInstance();
		Calendar startOfMonth = Calendar.getInstance();
		startOfMonth.set(Calendar.DATE, 1);
		//endOfMonth.set(Calendar.DATE, endOfMonth.getActualMaximum(Calendar.DATE));
		//Calendar now = Calendar.getInstance();
		//Calendar oneYearAgo = Calendar.getInstance();
		//oneYearAgo.set(Calendar.YEAR, oneYearAgo.get(Calendar.YEAR)-1);
		startDatePicker = new DatePicker(dateRange.getBeginning().getTime());
		endDatePicker = new DatePicker(dateRange.getEnd().getTime());
		refresh = new JButton("Refresh");
		presets = new JComboBox(Constants.presets);

		addDataColumns();
	}
	
	private void layoutComponents()
	{
		GridBagLayout layout = new GridBagLayout();
		setLayout(layout);
		GridBagConstraints constraints = layout.getConstraints(this);		
		constraints.gridx = 0;
		constraints.gridy = 0;
		constraints.anchor = GridBagConstraints.NORTHWEST;
		
		constraints.gridwidth = 2;
		add(entityButton, constraints);
		constraints.gridy++;
		add(accountButton, constraints);
		constraints.gridwidth = 1;
		
		constraints.gridy++;
		add(Box.createVerticalStrut(5), constraints);

		constraints.gridy++;
		add(new JLabel("Presets: "), constraints);
		constraints.gridx++;
		add(presets, constraints);
		constraints.gridx--;
		
		constraints.gridy++;
		add(new JLabel("Start: "), constraints);
		constraints.gridx++;
		add(startDatePicker, constraints);
		constraints.gridx--;
		constraints.gridy++;
		add(new JLabel("End: "), constraints);
		constraints.gridx++;
		add(endDatePicker, constraints);
		constraints.gridx--;
		
		constraints.gridy++;
		add(Box.createVerticalStrut(5));

		constraints.gridwidth = constraints.REMAINDER;
		constraints.gridy++;
		add(refresh, constraints);
	}
	
	private void setupEvents()
	{
		entityButton.addActionListener(this);
		accountButton.addActionListener(this);
		startDatePicker.addActionListener(this);
		endDatePicker.addActionListener(this);
		refresh.addActionListener(this);
		presets.addActionListener(this);
	}
	
	/**
	 * Add the standard statistics to the data table.
	 */
	public void addDataColumns()
	{
		if (startDatePicker != null && endDatePicker != null)
		{
			TableFactory.addFileCountColumnToTable(dataTable, new TimeRange(startDatePicker.getDate(), endDatePicker.getDate()), false);
			TableFactory.addNormalizedFileCountColumnToTable(dataTable, new TimeRange(startDatePicker.getDate(), endDatePicker.getDate()), false);
			TableFactory.addFileSizeColumnToTable(dataTable, new TimeRange(startDatePicker.getDate(), endDatePicker.getDate()), false);
			TableFactory.addNormalizedFileSizeColumnToTable(dataTable, new TimeRange(startDatePicker.getDate(), endDatePicker.getDate()), false);
			TableFactory.addFileDensityColumnToTable(dataTable, new TimeRange(startDatePicker.getDate(), endDatePicker.getDate()), false);
			TableFactory.addNormalizedFileDensityColumnToTable(dataTable, new TimeRange(startDatePicker.getDate(), endDatePicker.getDate()), false);
			//TableFactory.addFrequentLengthColumnToTable(dataTable, new TimeRange(startDatePicker.getDate(), endDatePicker.getDate()));
			//addIncrementColumns();
		}
	}
	
	/**
	 * Refresh the dataset with any new log data.
	 */
	protected void updateLogs()
	{
		AdiumLogReader.updateLogs(Application.logBaseFolder, Application.objectFolder, dataset, IMDataset.lastRead);
		IMDataset.lastRead = Calendar.getInstance();
	}
 	
	/**
	 * Update the data table.
	 */
 	public void updateTable()
 	{
 		updateTable(false);
 	}
 	
 	/**
 	 * Update the table columns.
 	 * 
 	 * @param init	whether we are initializing the table
 	 */
 	public void updateTable(boolean init)
 	{
 		application.removeIncrementColumns(init);
 		addDataColumns();
 		application.addIncrementColumns(init);
 	}
	
 	/**
 	 * 
 	 * @param viewType	the view type, Accounts vs Entities
 	 * @param init		whether we are initializing the table
 	 */
	public void setDataTable(String viewType, boolean init)
	{
		this.viewType = viewType;
		if (viewType.equals(ACCOUNT_VIEW))
		{
			dataTable = dataset.getAccountTable();
	 		addDataColumns();
			application.addIncrementColumns(init);
			application.updateDataTable(init);
		}
		else if (viewType.equals(ENTITY_VIEW))
		{
			dataTable = dataset.getEntityTable();
	 		addDataColumns();
			application.addIncrementColumns(init);
			application.updateDataTable(init);
		}
		else
			System.err.println("Illegal view type.");
	}

	public void actionPerformed(ActionEvent e) 
	{
		// if changing view...switch tables
		if (e.getSource() == accountButton)
		{
			application.removeIncrementColumns();
			setDataTable(ACCOUNT_VIEW, false);
	 		//application.addIncrementColumns();
		}
		else if (e.getSource() == entityButton)
		{
			application.removeIncrementColumns();
			setDataTable(ENTITY_VIEW, false);
	 		//application.addIncrementColumns();
		}
		else if (e.getSource() == refresh)
		{
			refreshDates();
			updateLogs();
			updateTable();
		}
		else if (e.getSource() == startDatePicker)
		{
			dateRange.getBeginning().setTime(startDatePicker.getDate());
			updateLogs();
			updateTable();
		}
		else if (e.getSource() == endDatePicker)
		{
			dateRange.getEnd().setTime(endDatePicker.getDate());
			updateLogs();
			updateTable();
		}
		else if (e.getSource() == presets)
		{
			if (presets.getSelectedItem().equals(Constants.PRESET_LAST_8_WEEKS)
					|| presets.getSelectedItem().equals(Constants.PRESET_LAST_YEAR))
			{
				if (presets.getSelectedItem().equals(Constants.PRESET_LAST_8_WEEKS))
					application.setIncrement(Increment.WEEK);
				else
					application.setIncrement(Increment.MONTH);
				Calendar endDate = Calendar.getInstance();
				endDate.set(endDate.get(Calendar.YEAR), endDate.get(Calendar.MONTH), endDate.get(Calendar.DATE), 23, 59, 59);
				Calendar startDate = Calendar.getInstance();
				startDate.set(endDate.get(Calendar.YEAR), endDate.get(Calendar.MONTH), endDate.get(Calendar.DATE), 0, 0, 0);
				// View the last 8 weeks
				if (presets.getSelectedItem().equals(Constants.PRESET_LAST_8_WEEKS))
					startDate.add(Calendar.DATE, -55);
				else
				{
					startDate.add(Calendar.YEAR, -1);
					startDate.add(Calendar.DATE, 1);
				}
				//dateRange = new TimeRange(startDate, endDate);
				try 
				{
					startDatePicker.setDate(startDate.getTime());
					endDatePicker.setDate(endDate.getTime());
				} 
				catch (PropertyVetoException e1) 
				{
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			else if (presets.getSelectedItem().equals(Constants.PRESET_FOREVER_BY_MONTH)
					|| presets.getSelectedItem().equals(Constants.PRESET_FOREVER_BY_YEAR))
			{
				if (presets.getSelectedItem().equals(Constants.PRESET_FOREVER_BY_MONTH))
					application.setIncrement(Increment.MONTH);
				else
					application.setIncrement(Increment.YEAR);
				Calendar endDate = Calendar.getInstance();
				endDate.set(endDate.get(Calendar.YEAR), endDate.get(Calendar.MONTH), endDate.get(Calendar.DATE), 23, 59, 59);
				//dateRange = new TimeRange(startDate, endDate);
				try 
				{
					startDatePicker.setDate(dataset.getFirstDate().getTime());
					endDatePicker.setDate(endDate.getTime());
				} 
				catch (PropertyVetoException e1) 
				{
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
	}

	/**
	 * Set the final date to now.
	 */
	public void refreshDates()
	{
		Calendar now = Calendar.getInstance();
		Calendar endDate = Calendar.getInstance();
		endDate.setTime(endDatePicker.getDate());
		if (now.after(endDate))
		{
			try 
			{
				endDatePicker.setDate(now.getTime());
			} 
			catch (PropertyVetoException e1) 
			{
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
}
